use clap::{Args, Parser, Subcommand};
use std::path::PathBuf;

#[derive(Subcommand, Debug)]
pub enum GenerateCommand {
    #[command(about = "Generate default runing config for service")]
    Config {
        #[arg(
            short,
            default_value_t = false,
            help = "Save to default file or print it to console"
        )]
        save: bool,
    },

    #[command(
        about = "Generate a configuration file based on the data of a normally running server"
    )]
    UpdateSetting {
        #[arg(
            short,
            default_value_t = false,
            help = "Save to default file or print it to console"
        )]
        save: bool,
    },

    #[command(about = "Generate a device list file based on the data of a normally running server")]
    DeviceList {
        #[arg(
            short,
            default_value_t = false,
            help = "Save to default file or print it to console"
        )]
        save: bool,
    },
}

#[derive(Args, Debug)]
pub struct RunArgument {
    #[arg(short, long, help = "Custom the path of config file")]
    config_path: Option<PathBuf>,

    #[arg(short, long, help = "The port will listen on")]
    port: Option<u16>,
}

#[derive(Subcommand, Debug)]
pub enum Command {
    #[command(about = "Run http service")]
    Run(RunArgument),

    #[command{
        about = "Generate configuration files"
    }]
    Generate {
        #[command(subcommand)]
        command: GenerateCommand,
    },
}

/// 命令行解析器
#[derive(Parser, Debug)]
#[command(
    name = "ctapi",
    version,
    about = "Providing API service for client of the game Coffee Tales",
    long_about = "This application will provide a simple HTTP service to control the update \
    and release of the game client. Meanwhile, it also features  the functionality of \
    generating configuration files."
)]
pub struct Argument {
    #[command(subcommand)]
    command: Command,
}

impl Argument {
    pub fn command(&self) -> &Command {
        &self.command
    }

    pub fn take_command(self) -> Command {
        self.command
    }
}

impl RunArgument {
    pub fn config_path(&self) -> Option<&PathBuf> {
        self.config_path.as_ref()
    }

    pub fn port(&self) -> Option<u16> {
        self.port.clone()
    }
}
